// Copyright (C) 2010  Joan Puigcerver Perez, <joapuipe@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

#ifndef __MEDIA_HPP__
#define __MEDIA_HPP__

#include <iostream>

#include <BasicTypes.hpp>

/**
 * \class Media
 *
 * Class used to represent the media types of a production.
 * Internally the media type is represented as an 8-bit unsigned integer.
 * This class can also represent a set of medias using bit operators (and, or).
 *
 */
class Media {
private:
  uint8_t _media; // Internal representation of the media
  
public:
  /** Code used for generic movies. */
  static const uint8_t ID_MOVIE;
  /** Code used for tv movies and tv shows. 
      IMDB.com does not distinguish them, which isn't cool. */
  static const uint8_t ID_TVMOVIE; 
  /** Code used for tv series. */
  static const uint8_t ID_TVSERIE;
  /** Code used for video games. */
  static const uint8_t ID_VGAME; 
  /** Code used for straight-to-video movies. */
  static const uint8_t ID_VIDEO;
  /** Code used for unknown media types. */
  static const uint8_t ID_UNKNOWN;  
  /** Wildcard very useful for filtering. */
  static const uint8_t ID_ALL;      

  /** String representation of generic movies. */
  static const char *  TAG_MOVIE;
  /** String representation of tv movies and tv shows. */
  static const char *  TAG_TVMOVIE;
  /** String representation of tv series. */
  static const char *  TAG_TVSERIE;
  /** String representation of video games. */
  static const char *  TAG_VGAME;
  /** String representation of straight-to-video movies. */
  static const char *  TAG_VIDEO;
  /** This is "Unknown". */
  static const char *  TAG_UNKNOWN;
  /** This is "All". */
  static const char *  TAG_ALL;  
  
  /**
   * Constructor that sets the object to unknown value.
   */
  Media();

  /**
   * Constructor that sets the media from a given 8-bit integer value.
   * @param media Code of the desired media value.
   */
  Media(const uint8_t media);
  
  /**
   * Constructor that sets the media from its string representation.
   * @param media Name of the desired media, e.g: TAG_MOVIE.
   */
  Media(const char * media);

  /**
   * Operator that sets the media to a given 8-bit int value.
   * @param media Code of the desired media value.
   */
  Media& operator = (const uint8_t media);
  
  /**
   * Comparator that checks if two Media objects are equal.
   * @param media The other Media object.
   */
  bool operator == (const Media& media) const;

  /**
   * Comparator that checks if a Media object is equal to a 
   * media represented as a 8-bit unsigned integer.
   * @param media Code of the second media.
   */
  bool operator == (const uint8_t media) const;

  /**
   * Distinct comparator that checks if two Media objects are
   * distinct.
   * @param media The other Media object.
   */
  bool operator != (const Media& media) const;

  /**
   * Distinct comparator that checks if a Media object is different to
   * a media represented as a 8-bit unsigned integer.
   * @param media Code of the second media.
   */
  bool operator != (const uint8_t media) const;

  /**
   * Operator that returns the internal code of the work as a
   * 8-bit unsigned int.
   */
  operator uint8_t () const;

  /**
   * Operator that returns the string representation of the media.
   */
  operator const char * () const;

  /**
   * Function that performs a bitwise AND operation between two Media objects.
   * This function is used to compare to Media objects treating each of them
   * as a set of medias.
   * @param media_a Media object interpreted as a set.
   * @param media_b Media object interpreted as a set.
   * \retval true The two media sets have a common value.
   * \retval false The two media sets does not have any common value.
   */
  static bool mask(const Media& media_a, const Media& media_b);

  /**
   * Friend method used to write the media's string representation 
   * to a ostream object.
   */
  friend std::ostream& operator << (std::ostream& os, const Media& media)
  {
    os << (const char *)media;
    return os;
  }
};

#endif
